package main

import (
	"fmt"
	"os"
	"os/signal"
	"reflect"
	"strings"
	"syscall"
	"time"

	"github.com/cosiner/zerver"
	"github.com/parnurzeal/gorequest"
	util "github.com/yaozijian/zerver_util"
)

type (
	student struct {
		Name  string
		Grade int
	}

	teacher struct {
		Name   string
		Salary int
	}

	fruit struct {
		util.HandlerBase `json:"-"`
		Name        string
		Color       string
		Price       float32
	}
)

func main() {

	server := zerver.NewServer()

	server.AddHandler("/students/:name", util.NewRestApiProxy("name", reflect.TypeOf(student{}), nil))

	proxy := util.NewRestApiProxy("name", reflect.TypeOf(teacher{}), util.GobBase64ResourceMaster)
	proxy.SetResourceManager("json", zerver.DefaultResourceMaster)

	server.AddHandler("/teachers/:name", proxy)
	//server.AddFilter("/teachers/:name", proxy)

	server.AddHandler("/fruits/apple", &fruit{Name: "Apple", Color: "Red", Price: 1.2})
	server.AddHandler("/fruits/banana", &fruit{Name: "Banana", Color: "Yellow", Price: 3.1})

	go func() {
		time.Sleep(time.Second)
		testTeacher()
	}()

	go waitInterrupt(server, proxy)

	if err := server.Start(&zerver.ServerOption{ListenAddr: ":4000"}); err != nil {
		fmt.Println(err)
		return
	}
}

func waitInterrupt(server *zerver.Server, proxy *util.RestApiProxy) {
	sigNotify := make(chan os.Signal, 10)
	signal.Notify(sigNotify, os.Interrupt, os.Kill,
		syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL)
	<-sigNotify
	//a, b, c := proxy.GetCounter()
	//fmt.Printf("getCnt=%d setCnt=%d delCnt=%d\n", a, b, c)
	server.Destroy()
	os.Exit(0)
}

func testTeacher() {

	req := gorequest.New().Timeout(time.Second * 5)
	data, err := util.GobBase64ResourceMaster.Marshal(&teacher{Name: "abc", Salary: 1000})
	if err != nil {
		return
	}

	reply, body, err2 := req.Post("http://127.0.0.1:4000/teachers/abc/").SendString(string(data)).End()
	if err2 != nil {
		fmt.Println("Post Error:", err)
	} else if reply.StatusCode != 200 {
		fmt.Printf("Post Error: code=%d status=%s\n", reply.StatusCode, reply.Status)
	} else {
		reply, body, err2 = req.Get("http://127.0.0.1:4000/teachers/abc/").End()
		if err2 == nil && reply.StatusCode == 200 {
			obj := &teacher{}
			if err2 := util.GobBase64ResourceMaster.Recieve(strings.NewReader(body), obj); err2 == nil {
				fmt.Println("Received teacher's info:", obj)
			}
		}
	}
}

func (this *fruit) Get(_ zerver.Request, reply zerver.Response) {
	if zerver.DefaultResourceMaster.Send(reply, "", this) != nil {
		reply.ReportInternalServerError()
	}
}

func (this *fruit) Post(req zerver.Request, reply zerver.Response) {
	val := &fruit{}
	if zerver.DefaultResourceMaster.Recieve(req, val) == nil && val.Price > 0.0 {
		this.Price = val.Price
	} else {
		reply.ReportBadRequest()
	}
}
